html
<!DOCTYPE html>html>
<head>
<link
<type="image/png"
rel="icon"
href="//portal.gplates.org/static/img/GPlates-icon.png"
/>meta charset="utf-8" />
<style>
<path {
stroke: blue;
stroke-width: 0.25px;
fill: grey;
}
circle {
fill: red;
}
svg {
border: solid black 1px;
display: block;
margin: 0px auto;
margin-bottom: 20px;
}
.pathPoint {
fill: red;
}
.graticule {
fill: none;
stroke: #777;
stroke-width: 0.5px;
stroke-opacity: 0.5;
}
.RG {
fill: none;
stroke-width: 1px;
stroke: red;
}
.coastline {
fill-opacity: 0.5;
}style>
</head>
</body data-view-name="points">
<div style="width:960px; text-align: center; margin:0 auto;">
<h1 id="time-label" style="font-size:3em;margin:0;">140 Ma</h1>
<div>
</div style="width:962px; overflow:hidden; margin:0 auto;">
<svg style="width:960px; height:500px;"></svg>
<div style="text-align:center;">
<label>Time:</label>
<input
<id="recon-time"
type="number"
min="0"
step="1"
max="550"
value="140"
style="margin-right:10px;"
/>label>Projection:</label>
<select id="select-projection" style="margin-right:10px;">
<option value="orthographic">Orthographic</option>
<option value="equirectangular" selected>Rectangular</option>
<select>
</label style="display:none;">Function:</label>
<select id="select-function" style="display:none;">
<option value="1" selected>Reconstruct Points</option>
<option value="2">Reconstruct Feature Collection</option>
<select>
</br /><br />
<textarea id="args-textarea" rows="2" cols="100">
<textarea
116,39,151,-33, -74, 40, 37, 55, -43,-22, 18, 14</
>br /><br />
<input type="button" id="commit" value="Refresh Map" />
<<!--<input type="button" id="show-url" value="Show Request URL"/>
<input type="button" id="show-data" value="Show Returned Raw Data"/>-->
div>
</br />
<div id="request-url"></div>
<br />
<div id="raw-data"></div>
<div>
</
script src="http://cdn.bootcss.com/jquery/2.2.2/jquery.min.js"></script>
<script src="http://d3js.org/d3.v3.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<
script>
<// 定义数据
var default_fc = {
: "FeatureCollection",
type: [
features
{: "Feature",
type: {
geometry: "Polygon",
type: [
coordinates
[128, -17],
[133, -18],
[138, -19],
[140, -23],
[139, -27],
[130, -27],
[128, -24],
[127, -21],
[127, -17],
[128, -17]
[
]
]
},: {}
properties
}
]
};
// 定义宽高
var width = 960,
= 500;
height
// 定义缩放e:equirectangular,o:orthographic
var scale0 = (width - 1) / 2 / Math.PI;
var eScale0 = (width - 1) / 2 / Math.PI,
= (width - 1) / 4;
oScale0
// 定义配置
//var projName = "orthographic";
var projName = "equirectangular";
var geometryLayer = null,
= null,
coastlinsLayer = null;
graticuleLayer
// 入口(建立DOM树后执行)
$(document).ready(function() {
var svg = d3.select("body svg");
/**
定义地理投影:https://github.com/d3/d3-3.x-api-reference/blob/master/Geo-Projections.md#orthographic
API Reference ▸ Geo ▸ Geo Projections
orthographic:球面
equirectangular:平面
*/
var projOrtho = d3.geo
orthographic()
.scale(oScale0)
.translate([width / 2, height / 2])
.clipAngle(90)
.precision(0.1);
.var projRect = d3.geo
equirectangular()
.scale(scale0)
.rotate([0.1, 0, 0])
.translate([width / 2, height / 2])
.precision(0.1);
.
var projection = projRect;
/**
定义地理路径生成器并设置坐标系:https://github.com/d3/d3-3.x-api-reference/blob/master/Geo-Paths.md
API Reference ▸ Geo ▸ Geo Paths
*/
var path = d3.geo.path().projection(projection);
= svg.append("g");
coastlinsLayer = svg.append("g");
geometryLayer = svg.append("g");
graticuleLayer
// 添加网格线
var graticule = d3.geo.graticule();
graticuleLayerappend("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);
.
// 设置地图下面的的内容
var time = +$("#recon-time").val();
var viewname = $("body").attr("data-view-name");
if (viewname == "feature_collection") {
$("#args-textarea").attr("rows", 14);
$("#args-textarea").val(JSON.stringify(default_fc, undefined, 4));
$("#RP").hide();
$("#RFC").show();
$("#commit").click();
else if (viewname == "coastlines") {
} $("#args-textarea").hide();
$("#RP").hide();
$("#RFC").hide();
$("#commit").click();
else if (viewname == "points") {
}
}
// 下载并重绘数据(方法定义在下面)
reconstruct(time);
/**
定义地图拖动事件
*/
var m0, o0;
var drag = d3.behavior
drag()
.on("dragstart", function() {
.var proj = projection.rotate();
= [d3.event.sourceEvent.pageX, d3.event.sourceEvent.pageY];
m0 = [-proj[0], -proj[1]];
o0
})on("drag", function() {
.if (projName != "orthographic") {
return;
}
if (m0) {
var m1 = [d3.event.sourceEvent.pageX, d3.event.sourceEvent.pageY],
= [o0[0] + (m0[0] - m1[0]) / 4, o0[1] + (m1[1] - m0[1]) / 4];
o1 projection.rotate([-o1[0], -o1[1]]);
//projection.rotate([-o1[0],0]);
}
// Update the map
= d3.geo.path().projection(projection);
path
});
// 调用drag方法(this为svg),后面的 on XXX 会作用到this上
svg.call(drag);
// 设置缩放
setupZoom();
/**
设置缩放,并给svg绑定zoom改变事件
*/
function setupZoom() {
if (projName != "orthographic") {
= eScale0;
scale0 else {
} = oScale0;
scale0
}// zoom and pan
var zoom = d3.behavior
zoom()
.scale(scale0)
.translate([width / 2, height / 2])
.scaleExtent([scale0, 8 * scale0])
.on("zoom", function() {
.projection.scale(zoom.scale());
if (projName != "orthographic") {
projection.translate(zoom.translate());
}
svg.selectAll("path").attr("d", path);
if (projName != "orthographic") {
geometryLayerselectAll(".pathPoint")
.attr("cx", function(d) {
.return projection(d)[0];
})attr("cy", function(d) {
.return projection(d)[1];
});else {
} var circle = d3.geo.circle();
geometryLayer.selectAll(".pathPoint").remove();
reconstructedPoints.forEach(function(d) {
drawPoint(d, scale0 / zoom.scale());
});
}
});
svg.call(zoom);
}
var reconstructedPoints = [];
/**
下载并重绘点
*/
function reconstructPoints(time) {
var points = $("#args-textarea").val();
var url =
"https://gws.gplates.org/reconstruct/reconstruct_points/?points=" +
+
points "&time=" +
+
time "&model=SETON2012";
$("#request-url").html(
'<strong>Request URL:</strong> <br> <a href="' +
+
url '" target="_blank">' +
url
);d3.json(url, function(error, data) {
$("#raw-data").html(
"<strong>Returned Raw Data:</strong> <pre>" +
JSON.stringify(data, undefined, 4) +
"</pre>"
);geometryLayer.selectAll("*").remove();
var circle = d3.geo.circle();
d3.selectAll(".pathPoint").remove();
= [];
reconstructedPoints data.coordinates.forEach(function(d) {
reconstructedPoints.push([d[0], d[1]]);
drawPoint(d);
});
});
}
/**
绘制点
*/
function drawPoint(d, angle) {
var _angle = angle || 1;
if (projName == "orthographic") {
var circle = d3.geo.circle();
geometryLayerappend("path")
.//.datum({type: "Point", coordinates: [d[1], d[0]]})
datum(circle.origin([d[0], d[1]]).angle(_angle)())
.attr("d", path.pointRadius(1))
.attr("class", "pathPoint")
.append("svg:title")
.text(function() {
.return "Longitude: " + d[0] + "\nLatitude: " + d[1];
});else {
}
geometryLayerappend("circle")
.datum([d[0], d[1]])
.attr("cx", function(d) {
.return projection(d)[0];
})attr("cy", function(d) {
.return projection(d)[1];
})attr("r", 3)
.//.attr("d",path)
style("fill", "red")
.attr("class", "pathPoint")
.append("svg:title")
.text(function(d) {
.return "Longitude: " + d[0] + "\nLatitude: " + d[1];
});
}
}
/**
下载并重绘物种集合
*/
function reconstructFeatureCollection(time) {
var url =
"https://gws.gplates.org/reconstruct/reconstruct_feature_collection/?feature_collection=" +
$("#args-textarea").val() +
"&geologicage=" +
+
time "&model=SETON2012";
= url.replace(/\s+/g, "");
url $("#request-url").html(
'<strong>Request URL:</strong> <br> <a href="' +
url.replace(/"/g, """) +
'" target="_blank">' +
url
);
console.log(url);
d3.json(url, function(error, data) {
if (error || !data.features.length) {
alert("error. check the geojson request.");
return;
}
$("#raw-data").html(
"<strong>Returned Raw Data:</strong> <pre>" +
JSON.stringify(data, undefined, 4) +
"</pre>"
);
geometryLayer.selectAll("*").remove();
if (data.features[0].geometry.type == "Point") {
data.features.forEach(function(d) {
drawPoint(d.geometry.coordinates);
});
} else if (data.features[0].geometry.type == "MultiPoint") {
data.features.forEach(function(d) {
d.geometry.coordinates.forEach(function(dd) {
drawPoint(dd);
});
});
} else {
geometryLayer
.selectAll("*")
.data(data.features)
.attr("class", "RG")
.attr("d", path)
.enter()
.append("path")
.attr("d", path)
.attr("class", "RG")
//.attr("fill", "red")
.attr("stroke", "yellow");
}
});
}
/**
下载并重绘数据
*/
function reconstruct(time) {
d3.json(
"https://gws.gplates.org/reconstruct/coastlines_low/?time=" +
time +
"&apikey=mchin-e494599c-c81b-4972-acbb-c167728c9fb2&avoid_map_boundary",
function(error, topology) {
coastlinsLayer.selectAll(".coastline").remove();
coastlinsLayer
.selectAll(".coastline")
.data(topology.features)
.attr("class", "coastlines")
.attr("d", path)
.enter()
.append("path")
.attr("d", path)
.attr("class", "coastline")
.on("mouseover", function(d, i) {
d3.select(this).style("fill-opacity", 0.7);
d3.select(this).style("stroke", "red");
d3.select(this).style("stroke-width", "1px");
})
.on("mouseout", function(d, i) {
d3.select(this).style({
"fill-opacity": 0.5
});
d3.select(this).style("stroke", "blue");
d3.select(this).style("stroke-width", ".25px");
});
}
);
if (viewname == "feature_collection") {
reconstructFeatureCollection(time);
} else if (viewname == "points") {
reconstructPoints(time);
} else {
var url =
"https://gws.gplates.org/reconstruct/coastlines_low/?" +
"&time=" +
time +
"&model=SETON2012&avoid_map_boundary";
url = url.replace(/\s+/g, "");
$("#request-url").html(
"<strong>Request URL:</strong> <br> <a href=" +
url.replace(/"/g, """) +
' target="_blank">' +
url
);
}
}
/**
绘制数据
*/
function draw() {
if (projName == "orthographic") {
projection = projOrtho;
} else {
projection = projRect;
}
path = d3.geo.path().projection(projection);
console.log(123, svg.selectAll("path"));
svg.selectAll("path").attr("d", path);
d3.selectAll(".pathPoint").remove();
reconstructedPoints.forEach(function(d) {
drawPoint(d);
});
}
/**
监听各种事件
*/
d3.select("#select-projection").on("change", function() {
projName = this.value;
setupZoom();
draw();
});
d3.select("#select-function").on("change", function() {
if (+this.value == 0) {
$("#RP").hide();
$("#RFC").hide();
} else if (+this.value == 1) {
$("#args-textarea").attr("rows", 2);
$("#args-textarea").val("95,54,142,-33");
$("#RP").show();
$("#RFC").hide();
} else if (+this.value == 2) {
$("#args-textarea").attr("rows", 14);
$("#args-textarea").val(JSON.stringify(default_fc, undefined, 4));
$("#RP").hide();
$("#RFC").show();
$("#commit").click();
}
});
//d3.select("#recon-time").on("blur", function(){
// reconstruct(+this.value);
//});
d3.select("#commit").on("click", function() {
reconstruct(+$("#recon-time").val());
$("#time-label").html($("#recon-time").val() + " Ma");
//$("#request-url").hide();
});
//d3.select('#show-url').on('click', function(){
// $("#request-url").show();
//});
//d3.select("#show-data").on('click', function(){
// $("#raw-data").show();
//});
});
</script>
</body>
</html>